﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bettzueche.RLGlue.TaskSpec {
    /// <summary>
    /// A <see cref="ITasksSpec"/> Version 2. Doesn't supports Discountfactor and Extrastring.
    /// </summary>
    /// <seealso cref="TaskSpecV30"/>
    class TaskSpecV20 : ITaskSpec {
        /*
         * "V:E:O:A:R"
         * The V(=2) corresponds to the version number of the task specification language.
         * E corresponds to the type of task being solved. 'e' if the task is episodic and 'c' if the task is continuing. 
         * O and A correspond to Observation and Action information respectively. 
         * Finally, the R corresponds to the range of rewards for the task. 
         * 
         * Within each of O, A and R a range can be provided, however if the values are unknown or 
         * infinite in magnitude, two special input values have been defined.
         * 
         * The format of O and A are identical. We will describe the form of O only. 
         * O contains three components, separated by underscore characters ("_") :
         * #dimensions_dimensionTypes_'dimensionRanges
         * 
         * 
         */

        /// <summary>
        /// Initializes a new instance of the <see cref="TaskSpecV20"/> class.<para>
        /// 
        /// </para>
        /// </summary>
        public TaskSpecV20() {
            //TODO
            Observations = new RLTypesSpec();
            Actions = new RLTypesSpec();
            Reward = new DoubleRange();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TaskSpecV20"/> class.
        /// </summary>
        /// <param name="observations">The observations.</param>
        /// <param name="actions">The actions.</param>
        /// <param name="reward">The reward.</param>
        /// <exception cref="ArgumentNullException">if one parameter is null</exception>
        internal TaskSpecV20(RLTypesSpec observations, RLTypesSpec actions, DoubleRange reward) {
            if (observations == null)
                throw new ArgumentNullException("observations");
            Observations = observations;
            if (actions == null)
                throw new ArgumentNullException("actions");
            Actions = actions;
            if (reward == null)
                throw new ArgumentNullException("reward");
            Reward = reward;
        }

        /// <summary>
        /// This Default Version
        /// </summary>
        public const int TS_VERSION = 2;

        #region ITaskSpec Members

        /// <summary>Task Spec Version (default 0 = not set)</summary>
        double _version = 0;
        /// <summary>
        /// Returns the string representation of the Task Spec object.
        /// </summary>
        public string Version {
            get { return _version.ToString(); }
            internal protected set {
                Double.TryParse(value,out _version);
            }
        }

        /// <summary>Problemtype ['e','c']. Standard = 'e'.</summary>
        char _episodic = 'e';

        public string Propblemtype {
            get { return _episodic+""; }
            internal protected set {
                if (value.StartsWith("e"))
                    _episodic = 'e';
                if (value.StartsWith("c"))
                    _episodic = 'c';
            }
        }

        /// <summary>
        /// Not supported.
        /// </summary>
        public double Discountfactor {
            get { throw new NotSupportedException("Task Spec 2.0 does not support discount factor."); }
        }

        /// <summary>
        /// Gets the observation ranges.
        /// </summary>
        public RLTypesSpec Observations {
            get;
            private set;
        }

        /// <summary>
        /// Gets the action ranges.
        /// </summary>
        public RLTypesSpec Actions {
            get;
            private set;
        }


        /// <summary>
        /// Gets the reward range.
        /// </summary>
        public DoubleRange Reward {
            get;
            internal protected set;
        }

        /// <summary>
        /// Not Supported.
        /// </summary>
        /// <value>
        /// Not Supported.
        /// </value>
        public string Extra {
            get {
                throw new NotSupportedException("Task Spec 2.0 does not support Extra String.");
            }
            set {
                throw new NotSupportedException("Task Spec 2.0 does not support discount factor.");
            }
        }

        /// <summary>
        /// Gets the task spec string.
        /// </summary>
        /// <returns></returns>
        public string ToTaskSpecString() {
            ITaskSpecSerializer serializer = new TaskSpecV2Serializer();
            return serializer.Serialize(this);
        }

        #endregion
    }
}
